<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/2/19 0019
 * Time: 下午 2:43
 */
namespace app\api\service;

use app\admin\model\Groupdetail;
use app\admin\model\Groupproduct;
use app\admin\model\Orderitem;
use app\admin\model\Stock;
use app\api\controller\Freight;
use app\common\BaseHelper;
use app\lib\exception\OrderException;
use app\lib\exception\ParameterException;
use app\lib\redis\Redis;
use think\Db;
use think\Exception;

class Group{
    //订单商品列表，也就是客户端传过来的products
    protected $oProducts;
    //真实的商品信息，从数据库查出来的（包括库存量）
    protected $products;
    protected $groupID;
    protected $groupType;
    protected $userid;
    protected $unigroupId = NULL;
    protected $addressId = NULL;
    protected $content = NULL;
    protected $formId = NULL;
    protected $invoice_id;
    protected $groupdetailId = NULL;
    protected $deliver_method = 1;
    public function makegroup($userid,$orderdata,$oProducts){
        $this->oProducts = $oProducts;
        $this->products = $this->getProductsByOrder($oProducts);
        $this->groupID = $orderdata['id'];
        $this->groupType = $orderdata['grouptype'];
        $this->orderType = $orderdata['orderType'];
        if($this->orderType == 1){
            $this->addressId = $orderdata['address'];
        }else{
            $this->pickuppoint_id = $orderdata['pickuppoint_id'];
            $this->deliver_method = 2;
        }
        $this->userid = $userid;
        $this->content = $orderdata['content'] ?? NULL;
        $this->unigroupId = $orderdata['unigroupId'] ?? NULL;
        $this->formId = $orderdata['form_id'] ?? NULL;
        $ExceptionInfo = [
            'pass' => true,
            'msg' => 'ok'
        ];
        $nowtime = time();
        $groupproduct = Groupproduct::where('id',$this->groupID)->where('status',1)->where('start_time','<=',$nowtime)->where('end_time','>=',$nowtime)->find();
        if(!$groupproduct){
            $ExceptionInfo['pass'] = false;
            $ExceptionInfo['msg'] = '此团购已过期或者被禁用';
            $order['ExceptionInfo'] = $ExceptionInfo;
            return $order;
        }
        $groupdetail = new Groupdetail();
        $grouping = $groupdetail->where(['group_id'=>$this->groupID,'member_id'=>$userid,'status'=>1,'is_pay'=>1])->find();
        if($grouping){
            $ExceptionInfo['pass'] = false;
            $ExceptionInfo['msg'] = '此商品您正在参加团购，不能重复参加';
            $order['ExceptionInfo'] = $ExceptionInfo;
            return $order;
        }
        $id = BaseHelper::getUUID();
        $this->groupdetailId = $id;
        $groupdetail->id = $id;
        $groupdetail->group_id = $this->groupID;
        $groupdetail->member_id = $this->userid;
        if($this->groupType==1){
            //参团(会传递unigroupId)
            $nowtime = time();
            $cproup = $groupdetail->where(['id'=>$this->unigroupId,'status'=>1,'is_pay'=>1])->where('end_date','>',$nowtime)->find();
            if(!$cproup){
                $ExceptionInfo['pass'] = false;
                $ExceptionInfo['msg'] = '此团不存在或者已经结束';
                $order['ExceptionInfo'] = $ExceptionInfo;
                return $order;
            }
            $groupdetail->originator = $cproup->originator;
            $groupdetail->unigroup_id = $cproup->id;
            $groupdetail->save();

        }else{
            //开团（团长）
            //userid = originator 生成unigroupId（唯一标识此团）
            $groupdetail->unigroup_id = $id;
            $groupdetail->originator = $this->userid;
            $groupdetail->save();
        }
        $this->unigroupId = $groupdetail->unigroup_id;
        //创建订单
        return $this->groupplace();
    }


    private function groupplace(){
        $status = $this->getOrderStatus();
        if(!$status['pass']){
            $status['order_id'] = -1;
            return $status;
        }
        //开始创建订单
        $orderSnap = $this->snapOrder($status);
        $order = $this->createOrder($orderSnap);
        $order['pass'] = true;
        return $order;
    }



    private function getOrderStatus()
    {
        $status = [
            'pass' => true,
            'orderPrice' => 0,
            'pStatusArray' => []
        ];
        foreach ($this->oProducts as $oProduct) {
            $pStatus = $this->getProductStatus($oProduct['product_id'], $oProduct['count'], $this->products);
            if (!$pStatus['haveStock']) {
                $status['pass'] = false;
            }
            $status['orderPrice'] += $pStatus['totalPrice'];
            array_push($status['pStatusArray'], $pStatus);
        }
        return $status;
    }

    private function getProductStatus($oPID, $oCount, $products)
    {
        $pIndex = -1;
        $pStatus = [
            'id' => null,
            'haveStock' => false,
            'count' => 0,
            'name' => '',
            'totalPrice' => 0
        ];
        for ($i = 0; $i < count($products); $i++) {
            if ($oPID == $products[$i]['id']) {
                $pIndex = $i;
            }
        }
        if ($pIndex == -1) {
            // 客户端传递的productid有可能根本不存在
            throw new OrderException(
                [
                    'msg' => 'id为' . $oPID . '的商品不存在，订单创建失败'
                ]);
        } else {
            $product = $products[$pIndex];
            $pStatus['id'] = $product['id'];
            $pStatus['name'] = $product['name'];
            $pStatus['count'] = $oCount;
            $pStatus['totalPrice'] = $product['price'] * $oCount;

            if ($product['marketable'] - $oCount >= 0) {
                $pStatus['haveStock'] = true;
            }
        }
        return $pStatus;
    }


    private function createOrder($snap)
    {
        Db::startTrans();
        try {
            $orderNo = Order::makeOrderNo();
            $order = new \app\admin\model\Order();
            $order->id = BaseHelper::getUUID();
            $Freight = new Freight();
            $order->address_id = $this->addressId;
            if(!empty($order->address_id)){
                $order->freight = $Freight->getFreight($this->oProducts,$order->address_id,$snap['orderPrice'],2);
            }else{
                $order->freight = 0;
            }
            $order_total = $snap['orderPrice'] + $order->freight;
            $order->member_id = $this->userid;
            $order->order_no = $orderNo;
            $order->order_price = $snap['orderPrice'];
            $order->total = $order_total;
            $order->total_count = $snap['totalCount'];
            $order->invoice_id = $this->invoice_id;
            $order->deliver_method = $this->deliver_method;
            $order->link_type = 2;
            $order->content = $this->content;
            $order->form_id = $this->formId;
            if($this->orderType == 2){
                $order->pickuppoint_id = $this->pickuppoint_id;
            }
            $order->invalid_time = time() + config('order.invalid_time');
            $order->save();
            $orderID = $order->id;
            $create_time = $order->create_date;
            foreach ($this->oProducts as &$p) {
                $p['id'] = BaseHelper::getUUID();
                $p['order_id'] = $orderID;
                foreach ($snap['pStatus'] as $v){
                    if($p['product_id'] == $v['id']){
                        $p['product_id'] =  $v['id'];
                        $p['product_name'] =  $v['name'];
                        $p['product_img'] = $v['main_img_url'];
                        $p['price'] = $v['price'];
                        $p['group_price'] = $v['group_price'];
                        $p['count'] = $v['count'];
                        $p['spec'] = $v['spec'];
                        $p['unit'] = $v['unit'];
                        break;
                    }
                }
            }
            $orderitem = new Orderitem();
            if($orderitem->saveAll($this->oProducts,false)){
                //预扣除库存 1.增加订单占用库存 2.扣除可销售库存
                $this->updateStock($this->oProducts);
                $this->orderQueue($order);
            }
            //往用户拼团详情表里插入orderid
            Groupdetail::where('id',$this->groupdetailId)->update(['order_id'=>$orderID]);
            Db::commit();
            return [
                'order_no' => $orderNo,
                'order_id' => $orderID,
                'create_time' => $create_time
            ];
        } catch (Exception $ex) {
            Db::rollback();
            throw $ex;
        }
    }

    private function orderQueue($order){
        $data = [];
        $data['order_id'] = $order->id;
        $data['invalid_time'] = $order->invalid_time;
        $redis = Redis::getRedisConn();
        $redis->RPush('order_list_queue',json_encode($data));
    }
    //预库存操作
    private function updateStock($oProducts){
        foreach ($oProducts as $v){
            $stock = Stock::where('product_id',$v['product_id'])->find();
            if($stock){
                $stock->setDec('marketable',$v['count']);
                $stock->setInc('order_stock',$v['count']);
            }else{
                throw new ParameterException([
                    'msg' => '仓库系统异常'
                ]);
            }
        }
    }

    // 预检测并生成订单快照
    private function snapOrder()
    {
        // status可以单独定义一个类
        $snap = [
            'orderPrice' => 0,
            'totalCount' => 0,
            'pStatus' => [],
            'snapName' => $this->products[0]['name'],
            'snapImg' => $this->products[0]['img_url'],
        ];

        if (count($this->products) > 1) {
            $snap['snapName'] .= '等';
        }

        foreach ($this->products as &$v){
            foreach ($this->oProducts as $value){
                if($v['id'] == $value['product_id']){
                    $v['count'] = $value['count'];
                    break;
                }
            }
        }
        for ($i = 0; $i < count($this->products); $i++) {
            $product = $this->products[$i];
            $pStatus = $this->snapProduct($product, $product['count']);
            $snap['orderPrice'] += $pStatus['group_price'] * $product['count'];
            $snap['totalCount'] += $product['count'];
            array_push($snap['pStatus'], $pStatus);
        }
        return $snap;
    }

    // 单个商品库存检测
    private function snapProduct($product, $oCount)
    {
        $pStatus = [
            'id' => null,
            'name' => null,
            'main_img_url'=>null,
            'count' => $oCount,
            'totalPrice' => 0,
            'price' => 0,
            'spec' => '',
            'unit' => 1
        ];

        $pStatus['counts'] = $oCount;
        // 以服务器价格为准，生成订单
        $pStatus['totalPrice'] = $oCount * $product['price'];
        $pStatus['name'] = $product['name'];
        $pStatus['id'] = $product['id'];
        $pStatus['main_img_url'] =$product['img_url'];
        $pStatus['price'] = $product['price'];
        $pStatus['group_price'] = $product['group_price'];
        $pStatus['confine_count'] = $product['confine_count'];
        $pStatus['spec'] = $product['spec'];
        $pStatus['unit'] = $product['unit'];
        return $pStatus;
    }

    /**
     * 根据订单ID进行库存量检测
     * @param $orderID
     * @return array
     */
    public function checkOrderStock($orderID){
        $oProducts = Orderitem::where('order_id','=',$orderID)->select();
        $this->oProducts = $oProducts;
        $this->products = $this->getProductsByOrder($oProducts);
        $status = $this->getOrderStatus();
        return $status;
    }




    // 根据订单查找真实商品
    private function getProductsByOrder($oProducts)
    {
        $oPIDs = [];
        $products = [];
        foreach ($oProducts as $item) {
            array_push($oPIDs, $item['product_id']);
        }
        if($oPIDs){
            // 为了避免循环查询数据库
            $join = [
                ['__STOCK__ b','b.product_id=a.id'],
                ['__GROUPPRODUCT__ c','c.product_id=a.id']
            ];
            $field = 'a.id,a.name,a.price,a.img_url,a.spec,a.unit,b.marketable,c.group_price,c.confine_count';
            $products = db('product')->alias('a')->where('a.id','in',$oPIDs)->join($join)->field($field)->select();
        }
        return $products;
    }
}